package com.imooc.pan.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.imooc.pan.converter.UserConverter;
import com.imooc.pan.entity.RPanUserFile;
import com.imooc.pan.entity.RPanUserStorage;
import com.imooc.pan.mapper.RPanUserStorageMapper;
import com.imooc.pan.service.RPanUserStorageService;
import com.imooc.pan.vo.UserStorageSizeVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
* @author Janson
* @description 针对表【r_pan_user_storage(用户存储空间表)】的数据库操作Service实现
* @createDate 2023-07-31 09:59:39
*/
@Service
public class RPanUserStorageServiceImpl extends ServiceImpl<RPanUserStorageMapper, RPanUserStorage> implements RPanUserStorageService {
    // 存储文件单位信息的map
    private Map<String,Integer> unitMap = new ConcurrentHashMap();
    
    @Autowired
    private UserConverter userConverter;
    
    /**
     * 获取的存储相关信息
     * @return
     */
    @Override
    public UserStorageSizeVO getUserStorage() {
        LambdaQueryWrapper<RPanUserStorage> queryWrapper = new LambdaQueryWrapper<>();
        // queryWrapper.eq(RPanUserStorage::getUserId, "1683719847686504448");
        queryWrapper.eq(RPanUserStorage::getUserId, StpUtil.getLoginIdAsLong());
        List<RPanUserStorage> userStorageList = this.list(queryWrapper);
        if (CollectionUtils.isNotEmpty(userStorageList)){
            RPanUserStorage userStorage = userStorageList.get(0);
            UserStorageSizeVO userStorageSizeVO = userConverter.userStorageSize2UserStorageSizeVO(userStorage);
            // 用户总存储大小，由 免费存储 和购买存储共同构成
            BigDecimal storageSize = userStorageSizeVO.getStorageSize();
            BigDecimal userBuyStorageSize = userStorage.getUserBuyStorageSize();
            BigDecimal finalStorageSize = storageSize.add(userBuyStorageSize);
            userStorageSizeVO.setStorageSize(finalStorageSize);
            BigDecimal percentage = userStorageSizeVO.getUsedSize().divide(finalStorageSize,2,0).multiply(new BigDecimal(100));
            userStorageSizeVO.setPercentage(percentage);
            return userStorageSizeVO;
        }
        return null;
    }
    
    /**
     * 更新用户存储已使用空间
     * @param userId
     * @param fileSizeDesc
     */
    @Override
    public Boolean addUserStorageUsed(Long userId, String fileSizeDesc,Integer folderFlag) {
        LambdaQueryWrapper<RPanUserStorage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RPanUserStorage::getUserId,userId);
        List<RPanUserStorage> userStorageList = this.list(queryWrapper);
        // 0：不是文件夹，才需要计算存储空间，1：是文件夹，不需要计算存储空间
        
        if (CollectionUtils.isNotEmpty(userStorageList) && 0 == folderFlag){
            RPanUserStorage userStorage = userStorageList.get(0);
            // 数字可能存在空格，去掉
            int index = fileSizeDesc.indexOf(' ');
            String fileSizeNum = fileSizeDesc.substring(0, index).trim();
            String fileSizeUnit = fileSizeDesc.substring(index + 1).trim();
            // 获取单位转换的参数
            int param = getParamByFilesizeUnit(fileSizeUnit);
            BigDecimal curFileSize =  new BigDecimal(fileSizeNum);
            // 计算占用的 GB 空间
            BigDecimal curFileSizeGB = curFileSize.divide(new BigDecimal(param),4,3);
            BigDecimal finalUsedSize = userStorage.getUsedSize().add(curFileSizeGB);
            userStorage.setUsedSize(finalUsedSize);
            // 更新已使用空间
            boolean isSuccess = updateById(userStorage);
            return isSuccess;
        }
       return true;
    }
    
    public Boolean isFull(Long userId,String fileSizeDesc,Integer folderFlag){
        LambdaQueryWrapper<RPanUserStorage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RPanUserStorage::getUserId,userId);
        List<RPanUserStorage> userStorageList = this.list(queryWrapper);
        // 0：不是文件夹，才需要计算存储空间，1：是文件夹，不需要计算存储空间
    
        if (CollectionUtils.isNotEmpty(userStorageList) && 0 == folderFlag){
            RPanUserStorage userStorage = userStorageList.get(0);
            // 数字可能存在空格，去掉
            int index = fileSizeDesc.indexOf(' ');
            String fileSizeNum = fileSizeDesc.substring(0, index).trim();
            String fileSizeUnit = fileSizeDesc.substring(index + 1).trim();
            // 获取单位转换的参数
            int param = getParamByFilesizeUnit(fileSizeUnit);
            BigDecimal curFileSize =  new BigDecimal(fileSizeNum);
            // 计算占用的 GB 空间
            BigDecimal curFileSizeGB = curFileSize.divide(new BigDecimal(param),4,3);
            BigDecimal finalUsedSize = userStorage.getUsedSize().add(curFileSizeGB);
            userStorage.setUsedSize(finalUsedSize);

            // 将添加文件 与 用户已使用空间 累加，与用户免费空间+已购买空间 比较，如果返回值-1，则小于，0，则等于，1则大于
            if (1 == finalUsedSize.compareTo(userStorage.getStorageSize().add(userStorage.getUserBuyStorageSize()))){
                return true;
            }
        }
        return false;
    }
    
    /**
     * 更新用户存储空间，服务之间调用使用
     * @param businessSize
     * @param duration
     */
    @Override
    public void updateUserStorageSize(BigDecimal businessSize, Integer duration) {
        // 3.更新用户存储空间
        // 构造更新条件
        LambdaQueryWrapper<RPanUserStorage> userStorageWrapper = new LambdaQueryWrapper<>();
        userStorageWrapper.eq(RPanUserStorage::getUserId,StpUtil.getLoginIdAsLong());
        RPanUserStorage userStorage = this.getOne(userStorageWrapper);
        // 获取用户之前购买的存储空间，若每购买，则为0
        BigDecimal oldUserBuyStorageSize = userStorage.getUserBuyStorageSize();
        // 当前订单购买的存储空间
        BigDecimal curBuySize = businessSize;
        BigDecimal newStorageSize = curBuySize.add(oldUserBuyStorageSize);
    
        // 设置新的购买存储
        userStorage.setUserBuyStorageSize(newStorageSize);
        // 计算购买存储套餐的过期时间
        DateTime empiredDateTime = DateUtil.offsetMonth(DateUtil.date(), duration);
        userStorage.setUserBuyEpiredTime(empiredDateTime);
    
        this.updateById(userStorage);
    }
    
    private  int getParamByFilesizeUnit(String unit){
        if (unitMap.isEmpty()){
            unitMap.put("GB",1);
            unitMap.put("MB",1 * 1024);
            unitMap.put("KB",2 * 1024);
            unitMap.put("bytes",3 * 1024);
        }
        return unitMap.get(unit);
    }
    
    /**
     * 删除文件史，更新存储大小，减少
     * @param userId
     * @param reconds
     */
    @Override
    public void substractUserStorageUsed(Long userId, List<RPanUserFile> reconds) {
        BigDecimal filesizeSum = new BigDecimal(0.00);
        List<BigDecimal> fileSizeList = reconds.stream()
                // 文件需要进行存储计算，文件夹不需要
                .filter(recond -> StringUtils.isNotBlank(recond.getFileSizeDesc()) && recond.getFolderFlag() == 0)
                .map(recond -> {
                    String fileSizeDesc = recond.getFileSizeDesc();
                    int index = fileSizeDesc.indexOf(' ');
                    // 数字可能存在空格，去掉
                    String fileSizeNum = fileSizeDesc.substring(0, index).trim();
                    String fileSizeUnit = fileSizeDesc.substring(index + 1).trim();
                    // 获取单位转换的参数
                    int param = getParamByFilesizeUnit(fileSizeUnit);
                    BigDecimal curFileSize = new BigDecimal(fileSizeNum);
                    // 计算占用的 GB 空间
                    BigDecimal curFileSizeGB = curFileSize.divide(new BigDecimal(param), 4, 3);
                    return curFileSizeGB;
                }).collect(Collectors.toList());
        // 计算需要减去的已删除文件存储大小
        for (BigDecimal filesize : fileSizeList) {
            filesizeSum = filesizeSum.add(filesize);
        }
        
        LambdaQueryWrapper<RPanUserStorage> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RPanUserStorage::getUserId,userId);
        List<RPanUserStorage> userStorageList = this.list(queryWrapper);
        if (CollectionUtils.isNotEmpty(userStorageList)){
            RPanUserStorage userStorage = userStorageList.get(0);
            BigDecimal curFileSize = filesizeSum;
            // 已使用空间 减去 删除文件大小，更新当前已使用空间
            BigDecimal finalUsedSize = userStorage.getUsedSize().subtract(filesizeSum);
            // 由于计算中采用了四舍五入的计算方式，因此需要此处进行处理，否则就出现 负数
            userStorage.setUsedSize(finalUsedSize.doubleValue() >= 0 ? finalUsedSize : BigDecimal.valueOf(0));
            updateById(userStorage);
        }
        
    }
}




